home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SoundMaker 2003 (Professional Edition)
/
SoundMaker 2003 - Professional Edition.iso
/
midi tool
/
midioxse.exe
/
DATA.1
/
fastarp.rex
< prev
next >
Wrap
OS/2 REXX Batch file
|
1999-03-27
|
5KB
|
178 lines
/* REXX: Simple MIDI Arpeggiator */
/* This Runs a fast single finger aprepggiator */
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
qName = MoxGetQueueName()
oldq = RxQueue( 'Set', qName )
ret = MOXSetQueueDataFormat( 'N' )
/* MIDI-OX creates a semaphore with same name as queue */
sem = SysOpenEventSem( qName )
running = (sem <> 0)
/* Use an Object REXX Queue to store note ons and offs */
noteQ = .queue~new
say "FastArp Initialized..."
do while running
someInput = (Queued() <> 0)
someChord = (noteQ~Items() <> 0)
do while someInput | someChord
now = MoxGetSystemTime()
if someInput
then do
pull timestamp status data1 data2
/* Sent by MIDI-OX to signify end of program */
if timestamp = 'END_DATA'
then do
running = 0
leave
end
if status = 144
then do /* only notes */
later = now + 100
event = .NoteEvent~New( later, 11, status, data1, data2 )
noteQ~Queue( event )
end
end
if someChord
then do
/* see if the queue head has expired yet */
event = noteQ~Peek()
if event~HasExpired( now )
then do
/* actually remove from Queue */
event = noteQ~Pull()
ret = MoxOutputMidi( event~status, event~note, event~velocity )
if ret <> 0
then do
msg = "Error code: " || ret
call RxMessageBox msg, '', 'OK', 'STOP'
end
if event~Cycle() then
noteQ~Queue( event )
end
end
someInput = (Queued() <> 0)
someChord = (noteQ~Items() <> 0)
end
if running
then do
/* queue is empty: you could do other processing here */
ret = SysWaitEventSem( sem )
if ret <> 0
then do
running = .false
call RxMessageBox "Sem Code:" || ret, "err", 'OK', 'STOP'
end
end
end
say "Exiting..."
call SysDropFuncs
exit
/* ========================================================== */
::class noteEvent subclass Object
::method Init
expose expire count status note velocity origNote
use arg expire, count, status, note, velocity
self~origNote = self~note
self~note = self~NextChordNote( self~note )
return
::method expire attribute
::method count attribute
::method status attribute
::method note attribute
::method velocity attribute
::method origNote attribute
::method HasExpired
use arg now
if now > self~expire then
return 1
return 0
::method Cycle
self~count = self~count - 1 /* one less to go */
select
when self~count > 8
then do
self~expire = self~expire + 100
self~note = self~NextChordNote( self~note )
return 1
end
when self~count > 5
then do
self~expire = self~expire + 100
if self~count = 6 then
self~note = self~origNote
else
self~note = self~PrevChordNote( self~note )
return 1
end
when self~count > 2
then do
self~expire = self~expire + 100
self~note = self~NextChordNote( self~note )
return 1
end
when self~count > 0
then do
self~expire = self~expire + 100
self~note = self~PrevChordNote( self~note )
return 1
end
otherwise return 0
end
return 0
::method NextChordNote
use arg lastNote
/* use Key of C for simplicity */
remaind = (lastNote + 4) // 12
select
when remaind = 1 then nextnote = lastNote + 3
when remaind = 3 then nextnote = lastNote + 3
when remaind = 6 then nextnote = lastNote + 3
when remaind = 8 then nextnote = lastNote + 3
when remaind = 10 then nextnote = lastNote + 3
otherwise nextNote = lastNote + 4
end
return nextNote
::method PrevChordNote
use arg curNote
/* use Key of C for simplicity */
remaind = curNote // 12
select
when remaind = 1 then prevnote = curNote - 4
when remaind = 4 then prevnote = curNote - 4
when remaind = 6 then prevnote = curNote - 4
when remaind = 9 then prevnote = curNote - 4
when remaind = 11 then prevnote = curNote - 4
otherwise prevNote = curNote - 3
end
return prevNote